package com.example.mp.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import lombok.extern.log4j.Log4j2;

import java.util.List;

/**
 * @ClassName ExcelUtils
 * @Description TODO
 * @Author hf
 * @Date 2022/12/28 17:28
 * @Version 1.0
 */
@Log4j2
public class ExcelUtils {

    public static final String FILE_NAME = "C:\\Users\\Administrator\\Desktop\\yn_ry\\" + System.currentTimeMillis() + ".xlsx";
    // 每个 sheet 写入的数据
    public static final int NUM_PER_SHEET = 200000;
    // 每次向 sheet 中写入的数据（分页写入）
    public static final int NUM_BY_TIMES = 50000;

    public static void exportData(List list, Class clazz) {
        String fileName = FILE_NAME;
        log.info("导出excel名称={}", fileName);
        long startTime = System.currentTimeMillis();
        // 获取数据
        // 获取 sheet 的个数
        int sheetNum = list.size() % NUM_PER_SHEET == 0 ? list.size() / NUM_PER_SHEET : list.size() / NUM_PER_SHEET + 1;
        // 获取每个sheet 写入的次数
        int writeNumPerSheet = NUM_PER_SHEET % NUM_BY_TIMES == 0 ? NUM_PER_SHEET / NUM_BY_TIMES : NUM_PER_SHEET / NUM_BY_TIMES + 1;
        // 最后一个 sheet 写入的数量
        int writeNumLastSheet = list.size() - (sheetNum - 1) * NUM_PER_SHEET;
        // 最后一个 sheet 写入的次数
        int writeNumPerLastSheet = writeNumLastSheet % NUM_BY_TIMES == 0 ? writeNumLastSheet / NUM_BY_TIMES : writeNumLastSheet / NUM_BY_TIMES + 1;
        // 指定写入的文件
        ExcelWriter excelWriter = EasyExcel.write(fileName, clazz).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
        for (int i = 0; i < sheetNum; i++) {
            String sheetName = "sheet" + i;
            WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetName).build();
            int writeNum = i == sheetNum - 1 ? writeNumPerLastSheet : writeNumPerSheet; // 每个sheet 写入的次数
            int endEndNum = i == sheetNum - 1 ? list.size() : (i + 1) * NUM_PER_SHEET; // 每个sheet 最后一次写入的最后行数
            for (int j = 0; j < writeNum; j++) {
                long l = System.currentTimeMillis();
                int startNum = i * NUM_PER_SHEET + j * NUM_BY_TIMES;
                int endNum = j == writeNum - 1 ? endEndNum : i * NUM_PER_SHEET + (j + 1) * NUM_BY_TIMES;
                excelWriter.write(list.subList(startNum, endNum), writeSheet);
                log.info("写入sheet={}，数据量={}-{}={}，耗时={}", sheetName, endNum, startNum, endNum - startNum, System.currentTimeMillis() - l);
            }
        }
        // 需要放入 finally 中
        if (excelWriter != null) {
            excelWriter.finish();
        }
        log.info("导出excel结束,总数据量={}，耗时={}ms", list.size(), System.currentTimeMillis() - startTime);
    }
}
